home *** CD-ROM | disk | FTP | other *** search
/ Network PC / Network PC.iso / amiga utilities / communication / internet / amitcp3.0b / src.lha / src / amitcp / api / amiga_generic2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-09-08  |  24.9 KB  |  742 lines

  1. RCS_ID_C="$Id: amiga_generic2.c,v 3.13 1994/04/07 20:46:52 jraja Exp $";
  2. /*
  3.  * Copyright (c) 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>
  4.  *                    Helsinki University of Technology, Finland.
  5.  *                    All rights reserved.
  6.  * 
  7.  * Created: Fri Dec 10 22:57:55 1993 too
  8.  * Last modified: Thu Apr  7 23:46:06 1994 jraja
  9.  *
  10.  * HISTORY
  11.  * $Log: amiga_generic2.c,v $
  12.  * Revision 3.13  1994/04/07  20:46:52  jraja
  13.  * Moved SBTC_COMPAT43 inside #ifdef notyet,
  14.  * organized tags in the autodoc to alphapetical order.
  15.  *
  16.  * Revision 3.12  1994/04/02  10:47:23  jraja
  17.  * Changed hErrno to be accessed via a pointer, added tag handling for the
  18.  * hErrnoPtr.
  19.  *
  20.  * Revision 3.11  1994/03/29  12:56:35  ppessi
  21.  * Added SBTC_COMPAT43 tag
  22.  *
  23.  * Revision 3.10  1994/03/22  08:37:28  jraja
  24.  * Added tag list entry for the SBTC_FDCALLBACK (fdCallback),
  25.  * added extern definitions for the __sys_nerr and __sys_errlist,
  26.  * updated SocketBaseTags autodoc.
  27.  *
  28.  * Revision 3.9  1994/02/26  18:05:56  jraja
  29.  * Changed socketbasetags.h to amitcp/socketbasetags.h.
  30.  *
  31.  * Revision 3.8  1994/02/16  06:25:51  jraja
  32.  * Added manual page for the SocketBaseTagList().
  33.  *
  34.  * Revision 3.7  1994/01/20  02:26:40  jraja
  35.  * Added errno size restriction and return value to the SetErrnoPtr().
  36.  * Added errnoPtr handling and rest of the error lists to the
  37.  * SocketBaseTagList().
  38.  *
  39.  * Revision 3.6  1994/01/18  22:55:06  jraja
  40.  * Added some checks and '%m' functionality to the syslog().
  41.  *
  42.  * Revision 3.5  1994/01/18  19:22:32  jraja
  43.  * Changed direct access to errnoPtr to baseErrno() macro (not all of them!)
  44.  *
  45.  * Revision 3.4  1994/01/13  07:05:24  jraja
  46.  * Added external declarations for h_errlist and h_nerr.
  47.  *
  48.  * Revision 3.3  1994/01/12  07:34:26  jraja
  49.  * Moved _getdtablesize() from amiga_generic.c to here.
  50.  *
  51.  * Revision 3.2  1994/01/12  07:23:28  jraja
  52.  * Added implementation of the _SocketBaseTagList(). Moved SetDTableSize and
  53.  * getlastfd() from amiga_generic.c to here. Removed redundant (empty) functions
  54.  *
  55.  * Revision 3.1  1994/01/04  14:12:28  too
  56.  * Moved some functions from amiga_generic.c. Added GetHErrno().
  57.  * Made cores to most AmiTCP/IP 3 functions.
  58.  *
  59.  */
  60.  
  61. #include <conf.h>
  62.  
  63. #include <sys/param.h>
  64. #include <sys/systm.h>
  65. #include <sys/syslog.h>
  66. #include <sys/errno.h>
  67.  
  68. #include <kern/amiga_includes.h>
  69.  
  70. #include <api/amiga_api.h>
  71. #include <api/amiga_libcallentry.h>
  72. #include <api/allocdatabuffer.h>
  73.  
  74. #include <api/apicalls.h>
  75.  
  76. #include <stdarg.h>
  77.  
  78. #include <amitcp/socketbasetags.h>
  79.  
  80. extern const char * const __sys_errlist[];
  81. extern const int __sys_nerr;
  82. extern const char * const h_errlist[];
  83. extern const int h_nerr;
  84. extern const char * const io_errlist[];
  85. extern const short io_nerr;
  86. extern const char * const sana2io_errlist[];
  87. extern const short sana2io_nerr;
  88. extern const char * const sana2wire_errlist[];
  89. extern const short sana2wire_nerr;
  90.  
  91. LONG /* SAVEDS */ RAF1(_Errno,
  92.                struct SocketBase *, libPtr, a6)
  93. #if 0
  94. {
  95. #endif
  96.   return (LONG)readErrnoValue(libPtr);
  97. }
  98.  
  99. LONG /* SAVEDS */ RAF3(_SetErrnoPtr,
  100.                struct SocketBase *,    libPtr,    a6,
  101.                VOID *,            err_p,    a0,
  102.                UBYTE,            size,    d0)
  103. #if 0     
  104. {
  105. #endif
  106.   if (size == 4 || size == 2 || size == 1) {
  107.     if (size & 0x1 || !((ULONG)err_p & 0x1)) {    /* either odd size or address even */
  108.       libPtr->errnoSize = size;
  109.       libPtr->errnoPtr = err_p;
  110.       return 0;
  111.     }
  112.   }
  113.  
  114.   writeErrnoValue(libPtr, EINVAL);
  115.   return -1;
  116. }
  117.  
  118. VOID SAVEDS RAF4(_Syslog,
  119.          struct SocketBase *,    libPtr,     a6,
  120.          ULONG,            pri,        d0,
  121.          const char *,        fmt,        a0,
  122.          va_list,        ap,        a1)
  123. #if 0
  124. {
  125. #endif
  126.   int saved_errno;
  127.   char fmt_cpy[1024];
  128.   register char *p = fmt_cpy;
  129.  
  130.   CHECK_TASK_VOID();
  131.  
  132.   /* check for invalid bits or no priority set */
  133.   if (!LOG_PRI(pri) || (pri &~ (LOG_PRIMASK|LOG_FACMASK)) ||
  134.       !(LOG_MASK(pri) & libPtr->LogMask))
  135.     return;
  136.  
  137.   saved_errno = readErrnoValue(libPtr);
  138.   if (saved_errno >= __sys_nerr)
  139.     saved_errno = 0;                        /* XXX */
  140.  
  141.   /* set default facility if none specified */
  142.   if ((pri & LOG_FACMASK) == 0)
  143.     pri |= libPtr->LogFacility;
  144.  
  145.   /* 
  146.    * Build the new format string
  147.    */
  148.   if (libPtr->LogTag) {
  149.     p += sprintf(p, libPtr->LogTag);
  150.   }
  151.   if (libPtr->LogStat & LOG_PID) {
  152.     p += sprintf(p, "[%lx]", libPtr->thisTask);
  153.   }
  154.   if (libPtr->LogTag) {
  155.     *p++ = ':';
  156.     *p++ = ' ';
  157.   }
  158.   /*
  159.    * Substitute error message for %m.
  160.    */
  161.   {
  162.     char ch, *t1;
  163.     const char *t2;
  164.  
  165.     for (t1 = p; ch = *fmt; ++fmt) {
  166.       if (ch == '%') {
  167.     if (fmt[1] == '%') {
  168.       ++fmt;
  169.       *t1++ = ch;
  170.     }
  171.     else if (fmt[1] == 'm') {
  172.       ++fmt;
  173.       for (t2 = __sys_errlist[saved_errno]; *t1 = *t2++; ++t1)
  174.         ;
  175.       continue;
  176.     }
  177.       }
  178.       *t1++ = ch;
  179.     }
  180.     *t1 = '\0';
  181.   }
  182.  
  183.   vlog(pri, fmt_cpy, ap);
  184. }
  185.  
  186. VOID SAVEDS RAF4(_SetSocketSignals,
  187.          struct SocketBase *,    libPtr,     a6,
  188.          ULONG,            SIGINTR,    d0,
  189.          ULONG,            SIGIO,        d1,
  190.          ULONG,            SIGURG,        d2)
  191. #if 0
  192. {
  193. #endif
  194.   CHECK_TASK_VOID();
  195.   /*
  196.    * The operations below are atomic so no need to protect them
  197.    */
  198.   libPtr->sigIntrMask = SIGINTR;
  199.   libPtr->sigIOMask = SIGIO;
  200.   libPtr->sigUrgMask = SIGURG;
  201. }
  202.  
  203. LONG /* SAVEDS */ RAF1(_getdtablesize,
  204.                struct SocketBase *,    libPtr, a6)
  205. #if 0
  206. {
  207. #endif
  208.  
  209.   return (LONG)libPtr->dTableSize;
  210. }
  211.  
  212. static int getLastSockFd(struct SocketBase * libPtr)
  213. {
  214.   int bit, lastmlong = (libPtr->dTableSize - 1) / NFDBITS;
  215.   unsigned long *smaskp, cmask, rmask;
  216.  
  217.   for (smaskp = (ULONG *)(libPtr->dTable + libPtr->dTableSize + lastmlong);
  218.        lastmlong >= 0; smaskp--, lastmlong--)
  219.     if (*smaskp)
  220.       break;
  221.  
  222.   if (lastmlong < 0)
  223.     return -1;
  224.  
  225.   cmask = *smaskp;
  226.   if ((rmask = cmask & 0xFFFF0000)) { bit = 16; cmask = rmask; }
  227.   else bit = 0;
  228.   if ((rmask = cmask & 0xFF00FF00)) { bit += 8; cmask = rmask; }
  229.   if ((rmask = cmask & 0xF0F0F0F0)) { bit += 4; cmask = rmask; }
  230.   if ((rmask = cmask & 0xCCCCCCCC)) { bit += 2; cmask = rmask; }
  231.   if ((rmask = cmask & 0xAAAAAAAA)) bit += 1;
  232.  
  233.   return lastmlong * 32 + bit;
  234. }
  235.  
  236. /*
  237.  * Set size of descriptor tab|e
  238.  */
  239. static LONG
  240. setdtablesize(struct SocketBase * libPtr, UWORD size)
  241. {
  242.   
  243.   LONG oldsize = (LONG)libPtr->dTableSize;
  244.   LONG copysize;
  245.   struct socket ** dTable;
  246.   int olddmasksize, copydmasksize, dmasksize;
  247.   
  248.   if (size < oldsize) {
  249.     int i;
  250.  
  251.     if ((i = getLastSockFd(libPtr)) > size)
  252.       size = i + 1;
  253.     copysize = size;
  254.   }
  255.   else
  256.     copysize = oldsize;
  257.  
  258.   olddmasksize    = (oldsize - 1) /  NFDBITS + 1;
  259.   copydmasksize    = (copysize - 1) / NFDBITS + 1;
  260.   dmasksize     = (size - 1) /       NFDBITS + 1;
  261.   
  262.   if ((dTable = AllocMem(size * sizeof (struct socket *) +
  263.              dmasksize * sizeof (fd_mask),
  264.              MEMF_PUBLIC|MEMF_CLEAR)) == NULL)
  265.     return oldsize;
  266.  
  267.   aligned_bcopy(libPtr->dTable, dTable, copysize * sizeof (struct socket *));
  268.   aligned_bcopy(libPtr->dTable + oldsize, dTable + size, 
  269.         copydmasksize * sizeof (fd_mask));
  270.   
  271.   FreeMem(libPtr->dTable, oldsize * sizeof (struct socket *) +
  272.       olddmasksize * sizeof (fd_mask));
  273.   
  274.   libPtr->dTable = dTable;
  275.   libPtr->dTableSize = size;
  276.   
  277.   return size;
  278. }
  279.  
  280.  
  281. #define CASE_LONG(code, baseField)\
  282.  case (code << SBTB_CODE): /* get */ \
  283.   *tagData = (ULONG)libPtr->baseField;\
  284.   break;\
  285.  case (code << SBTB_CODE) | SBTF_SET: /* set */\
  286.   *(ULONG *)&libPtr->baseField = *tagData;\
  287.   break
  288.  
  289. #define CASE_WORD(code, baseField)\
  290.  case (code << SBTB_CODE): /* get */ \
  291.   *tagData = (ULONG)libPtr->baseField;\
  292.   break;\
  293.  case (code << SBTB_CODE) | SBTF_SET: /* set */\
  294.   *(UWORD *)&libPtr->baseField = (UWORD)*tagData;\
  295.   break
  296.  
  297. #define CASE_BYTE(code, baseField)\
  298.  case (code << SBTB_CODE): /* get */ \
  299.   *tagData = (ULONG)libPtr->baseField;\
  300.   break;\
  301.  case (code << SBTB_CODE) | SBTF_SET: /* set */\
  302.   *(UBYTE *)&libPtr->baseField = (UBYTE)*tagData;\
  303.   break
  304.  
  305. #define CASE_FLAG(code, flag)\
  306.   case (code << SBTB_CODE): /* get */ \
  307.     *tagData = ((ULONG)libPtr->flags & (flag)) != 0;\
  308.     break;\
  309.   case (code << SBTB_CODE) | SBTF_SET: /* set */\
  310.     if (*tagData) \
  311.       *(UBYTE *)&libPtr->flags |= (flag);\
  312.     else \
  313.       *(UBYTE *)&libPtr->flags &= ~(flag);\
  314.     break
  315.  
  316.  
  317. /****** bsdsocket.library/SocketBaseTagList ***********************************
  318.  
  319.     NAME
  320.          SocketBaseTagList - Set/Get SocketBase attributes.
  321.  
  322.     SYNOPSIS
  323.          #include <amitcp/socketbasetags.h>
  324.  
  325.          ULONG SocketBaseTagList(struct TagItem *);
  326.  
  327.          error = SocketBaseTagList(taglist)
  328.          D0                        A0
  329.  
  330.          error = SocketBaseTags(ULONG tag, ...);
  331.  
  332.     FUNCTION
  333.         Set or get a list of (mostly) SocketBase instance dependent attributes
  334.         from the AmiTCP.
  335.  
  336.     INPUTS
  337.         These functions expect as their argument a standard tag list, one or
  338.         several array of struct TagItem as defined in the header file
  339.         <utility/tagitem.h>. The structure contains two fields: ti_Tag and
  340.         ti_Data.  The ti_Tag field contains tag code, which determines what
  341.         the SocketBaseTagList() should do with its argument, the ti_Data
  342.         field.
  343.  
  344.         The include file <amitcp/socketbasetags.h> defines macros for base tag
  345.         code values.  Base tag code macros begin with `SBTC_' (as Socket Base
  346.         Tag Code).  The base tag value defines what data item the tag item
  347.         refers.
  348.  
  349.         The tag code contains other information besides the referred data
  350.         item.  It controls, whether the SocketBaseTagList() should set or get
  351.         the appropriate parameter, and whether the argument of the tag in
  352.         question is passed by value or by reference.  
  353.  
  354.         The include file <amitcp/socketbasetags.h> defines the following
  355.         macros, which are used to construct the ti_Tag values from the base
  356.         tag codes:
  357.  
  358.              SBTM_GETREF(code) - get by reference
  359.              SBTM_GETVAL(code) - get by value
  360.              SBTM_SETREF(code) - set by reference
  361.              SBTM_SETVAL(code) - set by value
  362.  
  363.         If the actual data is stored directly into the ti_Data field, you
  364.         should use the 'by value' macros, SBTM_GETVAL() or SBTM_SETVAL().
  365.         However, if the ti_Data field contains a pointer to actual data, you
  366.         should use the 'by reference' macros, SBTM_GETREF() or SBTM_SETREF().
  367.         In either case the actual data should always be a LONG aligned to even
  368.         address.
  369.  
  370.         According the used tag naming scheme a tag which has "PTR" suffix
  371.         takes an pointer as its argument.  Don't mix the pointer arguments
  372.         with 'by reference' argument passing.  It is possible to pass a
  373.         pointer by reference (in which case the ti_Data is a pointer to the
  374.         actual pointer).
  375.  
  376.         The list of all defined base tag codes is as follows:
  377.  
  378.              SBTC_BREAKMASK       Tag data contains the INTR signal mask.  If
  379.                                   the calling task receives a signal in the
  380.                                   INTR mask, the AmiTCP interrupts current
  381.                                   function calls and returns with the error
  382.                                   code EINTR.  The INTR mask defaults to the
  383.                                   CTRL-C signal (SIGBREAKF_C, bit 12).
  384.  
  385.              SBTC_DTABLESIZE      Socket Descriptor Table size. This
  386.                                   defaults to 64.
  387.  
  388.              SBTC_ERRNO           The errno value. The values are defined in
  389.                                   <sys/errno.h>.
  390.  
  391.              SBTC_ERRNOBYTEPTR
  392.              SBTC_ERRNOWORDPTR
  393.              SBTC_ERRNOLONGPTR
  394.              SBTC_ERRNOPTR(size)  Set (only) the pointer to the errno
  395.                                   variable defined by the program.  AmiTCP
  396.                                   defines a value for this by default, but
  397.                                   the application must set the pointer (and
  398.                                   the size of the errno) with one of these
  399.                                   tags, if it wishes to access the errno
  400.                                   variable directly.
  401.  
  402.                                   The SBTC_ERRNOPTR(size) is a macro, which
  403.                                   expands to one of the other (BYTE, WORD or
  404.                                   LONG) tag codes, meaning that only 1, 2
  405.                                   and 4 are legal size values.
  406.  
  407.                                   The netlib autoinit.c sets the errno
  408.                                   pointer for the application, if the
  409.                                   application is linked with it.
  410.  
  411.              SBTC_ERRNOSTRPTR     Returns an error string pointer describing
  412.                                   the errno value given on input. You can not
  413.                                   set the error message, only get is allowed.
  414.  
  415.                                   On call the ti_Data must contain the error
  416.                                   code number.  On return the ti_Data is
  417.                                   assigned to the string pointer.  (*ti_Data,
  418.                                   if passed by reference).  See the file
  419.                                   <sys/errno.h> for symbolic definitions for
  420.                                   the errno codes.
  421.  
  422.              SBTC_FDCALLBACK      A callback function pointer for coordination
  423.                                   of file descriptor usage between AmiTCP and
  424.                                   link-library.  By default no callback is
  425.                                   called and the value of this pointer is
  426.                                   NULL.  The prototype for the callback
  427.                                   function is:
  428.  
  429.                                   int error = fdCallback(int fd, int action);
  430.                                       D0                     D0      D1
  431.  
  432.                                   where
  433.  
  434.                                   error -  0 for success or one of the error
  435.                                            codes in <sys/errno.h> in case of
  436.                                            error. The AmiTCP API function
  437.                                            that calls the callback usually
  438.                                            returns the 'error' back to the
  439.                                            caller without any further
  440.                                            modification.
  441.  
  442.                                   fd -     file descriptor number to take
  443.                                            'action' on.
  444.  
  445.                                   action - one of the following actions
  446.                                            (defined in
  447.                                            <amitcp/socketbasetags.h>):
  448.  
  449.                                            FDCB_FREE -  mark the 'fd' as
  450.                                                         unused on the link
  451.                                                         library structure. If
  452.                                                         'fd' represents a
  453.                                                         file handled by the
  454.                                                         link library, the
  455.                                                         error (ENOTSOCK)
  456.                                                         should be returned.
  457.  
  458.                                            FDCB_ALLOC - mark the 'fd'
  459.                                                         allocated as a
  460.                                                         socket.
  461.  
  462.                                            FDCB_CHECK - check if the 'fd' is
  463.                                                         free. If an error is
  464.                                                         returned, the 'fd' is
  465.                                                         marked as used in the
  466.                                                         AmiTCP/IP structures.
  467.  
  468.                                   The AmiTCP/IP calls the callback every time
  469.                                   a socket descriptor is allocated or freed.
  470.                                   AmiTCP/IP uses the FDCB_CHECK before actual
  471.                                   allocation to check that it agrees with the
  472.                                   link library on the next free descriptor
  473.                                   number.  Thus the link library doesn't need
  474.                                   to tell the AmiTCP if it creates a new file
  475.                                   handle in open(), for example.
  476.  
  477.                                   See file _chkufb.c on the net.lib sources
  478.                                   for an example implementation of the
  479.                                   callback function for the SAS/C.
  480.  
  481.              SBTC_HERRNO          The name resolver error code value. Get
  482.                                   this to find out why the gethostbyname()
  483.                                   or gethostbyaddr() failed. The values are
  484.                                   defined in <netdb.h>
  485.  
  486.              SBTC_HERRNOSTRPTR    Returns host error string for error number
  487.                                   in tag data.  Host error is set on
  488.                                   unsuccesful gethostbyname() and
  489.                                   gethostbyaddr() calls. See the file
  490.                                   <netdb.h> for the symbolic definitions for
  491.                                   the herrno valus.
  492.  
  493.                                   Notes for the SBTC_ERRNOSTRPTR apply also
  494.                                   to this tag code.
  495.  
  496.              SBTC_IOERRNOSTRPTR   Returns an error string for standard
  497.                                   AmigaOS I/O error number as defined in the
  498.                                   header file <exec/errors.h>.  Note that the
  499.                                   error number taken by this tag code is
  500.                                   positive, so the error codes must be
  501.                                   negated (to be positive).  The positive
  502.                                   error codes depend on the particular IO
  503.                                   device, the standard Sana-II error codes
  504.                                   can be retrieved by the tag code
  505.                                   SBTC_S2ERRNOSTRPTR.
  506.  
  507.                                   Notes for the SBTC_ERRNOSTRPTR apply also
  508.                                   to this tag code.
  509.  
  510.              SBTC_LOGFACILITY     Facility code for the syslog messages as
  511.                                   defined in the header file <sys/syslog.h>.
  512.                                   Defaults to LOG_USER.
  513.  
  514.              SBTC_LOGMASK         Sets the filter mask of the syslog
  515.                                   messages.  By default the mask is 0xff,
  516.                                   meaning that all messages are passed to the
  517.                                   log system.
  518.  
  519.              SBTC_LOGSTAT         Syslog options defined in <sys/syslog.h>.
  520.  
  521.              SBTC_LOGTAGPTR       A pointer to a string which is used by
  522.                                   syslog() to mark individual syslog
  523.                                   messages. This defaults to NULL, but is
  524.                                   set to the name of the calling program by
  525.                                   the autoinit code in netlib:autoinit.c.
  526.                                   This is for compatibility with pre-3.0
  527.                                   programs.
  528.  
  529.              SBTC_S2ERRNOSTRPTR   Returns an error string for a Sana-II
  530.                                   specific I/O error code as defined in the
  531.                                   header file <devices/sana2.h>.
  532.  
  533.                                   Notes for the SBTC_ERRNOSTRPTR apply also
  534.                                   to this tag code.
  535.  
  536.              SBTC_S2WERRNOSTRPTR  Returns an error string for a Sana-II Wire
  537.                                   Error code as defined in the header file
  538.                                   <devices/sana2.h>.
  539.  
  540.                                   Notes for the SBTC_ERRNOSTRPTR apply also
  541.                                   to this tag code.
  542.  
  543.              SBTC_SIGIOMASK       The calling task is sent the signals
  544.                                   specified by mask in tag data when
  545.                                   asynhronous I/O is to be notified. The
  546.                                   default value is zero, ie. no signal is
  547.                                   sent.
  548.  
  549.              SBTC_SIGURGMASK      The calling task is sent the signals
  550.                                   specified by mask in tag data when urgent
  551.                                   data for the TCP arrives. The default value
  552.                                   is zero, ie. no signal is sent.
  553.  
  554.     RESULT 
  555.         Returns 0 on success, and a (positive) index of the failing tag on
  556.         error.  Note that the value 1 means _first_ TagItem, 2 the second one,
  557.         and so on.  The return value is NOT a C-language index, which are 0
  558.         based.
  559.  
  560.     EXAMPLES
  561.         To be written, see net.lib sources for various examples.
  562.  
  563.     NOTES
  564.  
  565.     BUGS
  566.         None known.
  567.  
  568.     SEE ALSO
  569.         <netinclude:amitcp/socketbasetags.h>, <include:utility/tagitem.h>
  570.  
  571. *****************************************************************************
  572. *
  573. */
  574. #ifdef notyet
  575. /*
  576.              SBTC_COMPAT43        Tag data is handled as boolean.  If it is
  577.                                   true, AmiTCP/IP uses 4.3BSD compatible
  578.                                   sockaddr structure for this application.
  579.  
  580.                                   The unreleased AS225r2 uses also 4.3BSD-
  581.                                   compatible sockaddr structures.
  582.  
  583. */
  584. #endif
  585.  
  586. ULONG SAVEDS RAF2(_SocketBaseTagList,
  587.           struct SocketBase *,    libPtr,        a6,
  588.           struct TagItem *,    tags,        a0)
  589. #if 0     
  590. {
  591. #endif
  592.  
  593.   ULONG errIndex = 1;
  594.   ULONG tag;
  595.   ULONG *tagData;
  596.   short tmp;
  597.   UWORD utmp;
  598.  
  599.   static const char * const strErr = "Errlist lookup error";
  600.  
  601.   CHECK_TASK();
  602.  
  603.   while((tag = tags->ti_Tag) != TAG_END) {
  604.     if ((LONG)tag < 0) {        /* TAG_USER is the sign bit */
  605.       /* get pointer to the actual data */
  606.       tagData = ((UWORD)tag & SBTF_REF) ?
  607.     (ULONG *)tags->ti_Data : &tags->ti_Data;
  608.  
  609.       switch ((UWORD)tag & ~SBTF_REF) {
  610.  
  611.       CASE_LONG( SBTC_BREAKMASK,  sigIntrMask );
  612.  
  613.       CASE_LONG( SBTC_SIGIOMASK,  sigIOMask );
  614.  
  615.       CASE_LONG( SBTC_SIGURGMASK, sigUrgMask );
  616.  
  617.       case (SBTC_ERRNO << SBTB_CODE): /* get */ 
  618.     *tagData = (ULONG)readErrnoValue(libPtr);
  619.     break;
  620.       case (SBTC_ERRNO << SBTB_CODE) | SBTF_SET: /* set */
  621.         writeErrnoValue(libPtr, *tagData);
  622.     break;
  623.  
  624.       case (SBTC_HERRNO << SBTB_CODE): /* get */ 
  625.     *tagData = (ULONG)*libPtr->hErrnoPtr;
  626.     break;
  627.       case (SBTC_HERRNO << SBTB_CODE) | SBTF_SET: /* set */
  628.         *libPtr->hErrnoPtr = (LONG) *tagData;
  629.     break;
  630.  
  631.       case (SBTC_DTABLESIZE << SBTB_CODE): /* get */
  632.     *tagData = (ULONG)libPtr->dTableSize;
  633.     break;
  634.       case (SBTC_DTABLESIZE << SBTB_CODE) | SBTF_SET: /* set */
  635.     if ((tmp = (WORD)*tagData) > 0)
  636.       setdtablesize(libPtr, tmp);
  637.     break;
  638.  
  639.       CASE_LONG( SBTC_FDCALLBACK,   fdCallback );
  640.  
  641.       CASE_BYTE( SBTC_LOGSTAT,      LogStat );
  642.  
  643.       CASE_LONG( SBTC_LOGTAGPTR,    LogTag );
  644.  
  645.       case (SBTC_LOGFACILITY << SBTB_CODE): /* get */
  646.     *tagData = (ULONG)libPtr->LogFacility;
  647.     break;
  648.       case (SBTC_LOGFACILITY << SBTB_CODE) | SBTF_SET: /* set */
  649.     if ((utmp = (UWORD)*tagData) != 0 && (utmp &~ LOG_FACMASK) == 0)
  650.       libPtr->LogFacility = utmp;
  651.     break;
  652.  
  653.       case (SBTC_LOGMASK << SBTB_CODE): /* get */
  654.     *tagData = (ULONG)libPtr->LogMask;
  655.     break;
  656.       case (SBTC_LOGMASK << SBTB_CODE) | SBTF_SET: /* set */
  657.     if ((utmp = (UWORD)*tagData) != 0)
  658.       libPtr->LogMask = (UBYTE)utmp;
  659.     break;
  660.  
  661.       case SBTC_ERRNOSTRPTR << SBTB_CODE:
  662.     /* get index */
  663.     utmp = (UWORD)*tagData;
  664.     /* return string pointer */
  665.     *tagData = (ULONG)((utmp >= __sys_nerr) ?
  666.                strErr : __sys_errlist[utmp]);
  667.     break;
  668.       case SBTC_HERRNOSTRPTR << SBTB_CODE:
  669.     /* get index */
  670.     utmp = (UWORD)*tagData;
  671.     /* return string pointer */
  672.     *tagData = (ULONG)((utmp >= h_nerr) ?
  673.                strErr : h_errlist[utmp]);
  674.     break;
  675.       case SBTC_IOERRNOSTRPTR << SBTB_CODE:
  676.     /* get index */
  677.     utmp = (UWORD)*tagData;
  678.     /* return string pointer */
  679.     *tagData = (ULONG)((utmp >= io_nerr) ? 
  680.                strErr : io_errlist[utmp]);
  681.     break;
  682.       case SBTC_S2ERRNOSTRPTR << SBTB_CODE:
  683.     /* get index */
  684.     utmp = (UWORD)*tagData;
  685.     /* return string pointer */
  686.     *tagData = (ULONG)((utmp >= sana2io_nerr) ?
  687.                strErr : sana2io_errlist[utmp]);
  688.     break;
  689.       case SBTC_S2WERRNOSTRPTR << SBTB_CODE:
  690.     /* get index */
  691.     utmp = (UWORD)*tagData;
  692.     /* return string pointer */
  693.     *tagData = (ULONG)((utmp >= sana2wire_nerr) ?
  694.                strErr : sana2wire_errlist[utmp]);
  695.     break;
  696.  
  697.       case (SBTC_ERRNOBYTEPTR << SBTB_CODE) | SBTF_SET: /* set */
  698.         if (SetErrnoPtr(libPtr, (VOID *)*tagData, 1) < 0)
  699.       return errIndex;
  700.         break;
  701.       case (SBTC_ERRNOWORDPTR << SBTB_CODE) | SBTF_SET: /* set */
  702.         if (SetErrnoPtr(libPtr, (VOID *)*tagData, 2) < 0)
  703.       return errIndex;
  704.         break;
  705.       case (SBTC_ERRNOLONGPTR << SBTB_CODE) | SBTF_SET: /* set */
  706.         if (SetErrnoPtr(libPtr, (VOID *)*tagData, 4) < 0)
  707.       return errIndex;
  708.         break;
  709.  
  710.       CASE_LONG( SBTC_HERRNOLONGPTR, hErrnoPtr );
  711.  
  712. #ifdef notyet
  713.       CASE_FLAG( SBTC_COMPAT43, SBFB_COMPAT43 );
  714. #endif
  715.  
  716.       default:
  717.     return errIndex;
  718.       }
  719.     }
  720.     else {            /* TAG_USER not set */
  721.       switch(tags->ti_Tag) {
  722.       case TAG_IGNORE:
  723.     break;
  724.       case TAG_MORE:
  725.     tags = (struct TagItem *)tags->ti_Data;
  726.     errIndex++;
  727.     continue;
  728.       case TAG_SKIP:
  729.     tags++; errIndex++;
  730.     break;
  731.       default:
  732.         return errIndex;    /* fail */
  733.       }
  734.     }
  735.     
  736.     tags++; errIndex++;
  737.   }
  738.   
  739.   return 0;
  740. }
  741.  
  742.